#include "message-server-client.h"
#include "file-list.h"
#include "log.h"

namespace messages {

// LOGIN
REGISTER_MESSAGE_TYPE(LOGIN, Login);

Login::Login() : Message(LOGIN) {
}

Login::Login(ClientId id, quint32 ip, quint16 port,
             QByteArray name, QByteArray email) :
    Message(LOGIN),
    id_(id), ip_(ip), port_(port), name_(name), email_(email) {
}

void Login::parse_array(const QByteArray* array, int* position) {
    Message::parse_array(array, position);

    ByteArrayParser p(array, position);
    p.parse(&id_);
    p.parse(&ip_);
    p.parse(&port_);
    p.parse(&name_);
    p.parse(&email_);
}

void Login::build_array(QByteArray* array) const {
    Message::build_array(array);

    ByteArrayAppender a(array);
    a.append(id_);
    a.append(ip_);
    a.append(port_);
    a.append(name_);
    a.append(email_);
}

// S_QUERY
REGISTER_MESSAGE_TYPE(S_QUERY, SQuery);

SQuery::SQuery() : Message(S_QUERY) {
}

SQuery::SQuery(const QByteArray& query,quint32 query_id):
    Message(S_QUERY), query_(query), query_id_(query_id) {
}

void SQuery::parse_array(const QByteArray* array, int* position) {
    Message::parse_array(array, position);

    ByteArrayParser p(array, position);
    p.parse(&query_);
    p.parse(&query_id_);
}

void SQuery::build_array(QByteArray* array) const {
    Message::build_array(array);

    ByteArrayAppender a(array);
    a.append(query_);
    a.append(query_id_);
}

// S_LIST_SEGMENT
REGISTER_MESSAGE_TYPE(S_LIST_SEGMENT, ListSegment);

ListSegment::ListSegment() : Message(S_LIST_SEGMENT) {
    list_ = NULL;
}

ListSegment::ListSegment(const FileList* list, int start, int end, int id) :
   Message(S_LIST_SEGMENT), id_(id) {

   list_ = new FileList;
   for (int i = start; i < end; ++i)
       list_->push_back(list->at(i)->clone());
}

ListSegment::~ListSegment() {
    delete list_;
}

void ListSegment::parse_array(const QByteArray* array, int* position) {
    CHECK_EQ(list_, (void*)NULL);

    Message::parse_array(array, position);

    ByteArrayParser p(array, position);
    p.parse(&id_);         // citim id-ul
    quint32 count = 0;
    p.parse(&count);       // citim numarul de fisiere stocate

    // citim fisiere unul cate unul
    list_ = new FileList();
    for (int i = 0; i < (int)count; ++i) {
        FileList::File* file = new FileList::File;
        file->parse(array, position);
        list_->push_back(file);
    }
}

void ListSegment::build_array(QByteArray* array) const {
    Message::build_array(array);

    ByteArrayAppender a(array);
    a.append(id_);
    a.append(quint32(list_->size()));
    for (int i = 0; i < list_->size(); ++i)
        list_->at(i)->append(array);
}

// ACK_LIST_SEGMENT
REGISTER_MESSAGE_TYPE(ACK_LIST_SEGMENT, AckListSegment);

// TODO(alexandru): finish
AckListSegment::AckListSegment() : Message(ACK_LIST_SEGMENT) {
}

AckListSegment::AckListSegment(quint32 id) :
    Message(ACK_LIST_SEGMENT), id_(id) {
}

void AckListSegment::parse_array(const QByteArray* array, int* position) {
    Message::parse_array(array, position);

    ByteArrayParser p(array, position);
    p.parse(&id_);
}

void AckListSegment::build_array(QByteArray* array) const {
    Message::build_array(array);

    ByteArrayAppender a(array);
    a.append(id_);
}


// QueryResult
REGISTER_MESSAGE_TYPE(S_QUERY_RESULT, QueryResult);

QueryResult::QueryResult() : Message(S_QUERY_RESULT) {
}

QueryResult::QueryResult(
        quint32 query_id, ClientId client,
        quint32 address, quint16 port, 
    	const QByteArray& filename,
        const FingerPrint& fingerprint,
        quint32 size) :
    Message(S_QUERY_RESULT),
    filename_(filename),
    fingerprint_(fingerprint) {

	client_ = client;
	address_ = address;
	port_ = port;
	query_id_ = query_id;
    size_ = size;
}

void QueryResult::build_array(QByteArray* array) const {
    Message::build_array(array);

    ByteArrayAppender a(array);
    a.append(query_id_);
    a.append(client_);
    a.append(address_);
    a.append(port_);
    a.append(filename_);
    a.append(fingerprint_);
    a.append(size_);
    
}

void QueryResult::parse_array(const QByteArray* array, int* position) {
    Message::parse_array(array, position);

    ByteArrayParser p(array, position);
    
    p.parse(&query_id_);
    p.parse(&client_);
    p.parse(&address_);
    p.parse(&port_);
    p.parse(&filename_);
    p.parse(&fingerprint_);
    p.parse(&size_);
}

}
